﻿using System.Collections.Generic;

namespace System.Linq.Expressions
{
    static public class ExpressionExtentions
    {
        #region Static public methods

        /// <summary>
        /// Converts expression like x => x.Something.Anything.Name to members path:
        /// "Something.Anything.Name"
        /// </summary>        
        static public string ConvertToMembersPath<T, TResult>(this Expression<Func<T, TResult>> expression)
        {
            return GetMemberNames(expression.Body).Join(".");
        }

        #endregion

        #region Static private or internal methods

        static private IEnumerable<string> GetMemberNames(Expression expression)
        {
            if (expression is ConstantExpression || expression is ParameterExpression)
                yield break;

            if (expression is UnaryExpression)
            {
                foreach (string memberName in GetMemberNames(((UnaryExpression)expression).Operand))
                    yield return memberName;
                
                yield break;
            }

            var memberExpression = expression as MemberExpression;

            if (memberExpression == null)
                throw new InvalidOperationException("Current lambda expression can not be converted to members path");

            foreach (string memberName in GetMemberNames(memberExpression.Expression))
                yield return memberName;

            yield return memberExpression.Member.Name;
        }

        #endregion
    }
}